﻿using GrainManage.Entities;
using System.Web.Mvc;

namespace GrainManage.Server.Attribute
{
    public class GrainManagePerformanceAttribute : FilterAttribute, IActionFilter, IResultFilter
    {
        private readonly System.Diagnostics.Stopwatch timer;
        private readonly System.Diagnostics.Stopwatch actionTimer;
        private readonly System.Diagnostics.Stopwatch resultTimer;

        public GrainManagePerformanceAttribute()
        {
            if (IsTimeSpanNeeded)
            {
                timer = new System.Diagnostics.Stopwatch();
                actionTimer = new System.Diagnostics.Stopwatch();
                resultTimer = new System.Diagnostics.Stopwatch();
            }
        }

        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            StartWatch(timer);
            StartWatch(actionTimer);
            //base.OnActionExecuting(filterContext);
        }

        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
            //base.OnActionExecuted(filterContext);
            if (IsTimeSpanNeeded)
            {
                actionTimer.Stop();
                var result = filterContext.Result as NewtonsoftJsonResult;
                if (result != null && result.Data != null)
                {
                    var data = result.Data as BaseOutputModel;
                    if (data != null)
                    {
                        data.Status.TimeSpan = string.Format("{0} ms", actionTimer.ElapsedMilliseconds);
                    }
                }
            }
        }

        public void OnResultExecuting(ResultExecutingContext filterContext)
        {
            StartWatch(resultTimer);
            //base.OnResultExecuting(filterContext);
        }

        public void OnResultExecuted(ResultExecutedContext filterContext)
        {
            //base.OnResultExecuted(filterContext);
            if (IsTimeSpanNeeded)
            {
                timer.Stop();
                resultTimer.Stop();
                var builder = new System.Text.StringBuilder();
                builder.AppendLine("ActionTimeSpan: " + actionTimer.ElapsedMilliseconds + " ms");
                builder.AppendLine("ResultTimeSpan: " + resultTimer.ElapsedMilliseconds + " ms");
                builder.AppendLine("TotalTimeSpan: " + timer.ElapsedMilliseconds + " ms");
                LogUtil.Write(builder.ToString(), LogLevel.Debug, null);
            }
        }

        private static bool IsTimeSpanNeeded
        {
            get
            {
                return AppConfig.GetValue<bool>("CalculateTimeSpan");
            }
        }

        private void StartWatch(System.Diagnostics.Stopwatch timer)
        {
            if (IsTimeSpanNeeded)
            {
                timer.Start();
            }
        }
    }
}